package com.tencent.examples.blueking.mysql.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tencent.bk.utils.blueking.tools.AliObjectConversion;
import com.tencent.bk.utils.blueking.tools.DateTimeUtils;
import com.tencent.bk.utils.blueking.tools.StringConverters;
import com.tencent.examples.blueking.extend.QueryParam;
import com.tencent.examples.blueking.mongo.service.ObjectBaseService;
import com.tencent.examples.blueking.mysql.extend.biz.CrudBiz;
import com.tencent.examples.blueking.mysql.model.BkStoreTime;
import com.tencent.examples.blueking.mysql.model.JobStoreTime;
import com.tencent.examples.blueking.mysql.repository.BkStoreTimeRepository;
import com.tencent.examples.core.processor.BlueKingProcessor;
import com.tencent.examples.core.processor.dto.BkResult;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.Predicate;
import java.util.*;

@Service
public class BkStoreTimeService extends CrudBiz<BkStoreTimeRepository, BkStoreTime> {

    /**
     * EntityManager持久层对象
     */
    @PersistenceContext
    private EntityManager entityManager;
    @Autowired
    JobStoreTimeService jobStoreTimeService;
    @Autowired
    ObjectBaseService objectBaseService;
    @Autowired
    BlueKingProcessor blueKingProcessor;

    @Override
    public Specification<BkStoreTime> getSearchCondition(Map<String, String> queryHash) {
        return (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>(); //所有的断言
            predicates.add(criteriaBuilder.equal(root.get("deleteStatus").as(Boolean.class), false));
            Long globalId = StringConverters.ToLong(queryHash.get("globalId"));
            if (globalId != null) {
                predicates.add(criteriaBuilder.equal(root.get("globalId").as(Long.class), globalId));
            }
            Integer dayOfWeekMon1Sun7 = StringConverters.ToInteger(queryHash.get("dayOfWeekMon1Sun7"));
            if (dayOfWeekMon1Sun7 != null) {
                predicates.add(criteriaBuilder.equal(root.get("dayOfWeekMon1Sun7").as(Integer.class), dayOfWeekMon1Sun7));
            }
            String businessCloseTime = queryHash.get("businessCloseTime");
            if (StringUtils.isNotEmpty(businessCloseTime)) {
                predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("businessCloseTime").as(String.class), businessCloseTime));
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
    }

    @Override
    @Transactional(readOnly = true)
    public List<BkStoreTime> findList(QueryParam queryParam) {
        return dao.findAll(getSearchCondition(queryParam.getSqlMap()));
    }

    @Override
    @Transactional(readOnly = true)
    public Page<BkStoreTime> findList(Pageable pageable, QueryParam queryParam) {
        return dao.findAll(getSearchCondition(queryParam.getSqlMap()), pageable);
    }

    @Override
    @Transactional(readOnly = true)
    public BkStoreTime findModel(Long id) {
        return dao.findOne(id);
    }

    @Override
    @Transactional(readOnly = false)
    public void add(BkStoreTime model) {
        model.setCreateDate(new Date());
        dao.save(model);
    }

    @Override
    @Transactional(readOnly = false)
    public void update(BkStoreTime model) {
        BkStoreTime existModel = dao.findOne(model.getId());
        BeanUtils.copyProperties(model, existModel);
        existModel.setUpdateDate(new Date());
    }

    @Override
    @Transactional(readOnly = false)
    public void addOrUpdate(BkStoreTime model) {
        if (model.getId() != null && model.getId() > 0) {
            update(model);
        } else {
            add(model);
        }
    }

    @Override
    @Transactional(readOnly = false)
    public void delete(Long id) {
        dao.delete(id);
    }

    @Override
    @Transactional(readOnly = false)
    public void delete_logic(BkStoreTime model) {
        BkStoreTime bkStoreTime = dao.findOne(model.getId());
        bkStoreTime.setDeleteStatus(true);
    }

    /**
     * 查询每天的门店的开店闭店时间
     *
     * @param week 星期几
     * @return
     */
    public List getStoreTimeDayJob(Integer week) {
        String sql = "SELECT business_open_time,business_close_time,GROUP_CONCAT(DISTINCT inst_id) FROM bk_store_time \n" +
                "WHERE delete_status=FALSE \n" +
                "AND business_close_time!='' AND business_close_time IS NOT NULL\n" +
                "AND business_open_time!='' AND business_open_time IS NOT NULL\n" +
                "AND global_id IS NOT NULL AND inst_id IS NOT NULL\n" +
                "AND day_of_week_mon1sun7=" + week + "\n" +
                "GROUP BY business_open_time,business_close_time\n";
        return entityManager.createNativeQuery(sql).getResultList();
    }


    /**
     * 开始保存门店信息到门店表中
     *
     * @param global_id             门店在cmdb和mq的唯一主键
     * @param store_name            门店名称
     * @param begin_date            开店日期
     * @param end_date              闭店日期
     * @param business_open_time    开店时间点
     * @param business_close_time   闭店时间点
     * @param day_of_week_mon1_sun7 星期几
     */
    public void messageSaveStore(Long global_id, String store_name, String begin_date, String end_date, String business_open_time
            , String business_close_time, Integer day_of_week_mon1_sun7, Integer inst_id) {
        QueryParam queryParam = new QueryParam();
        queryParam.getSqlMap().put("globalId", global_id + "");
        List<BkStoreTime> bkStoreTimes = this.findList(queryParam);
        BkStoreTime bkStoreTime;
        if (CollectionUtils.isNotEmpty(bkStoreTimes)) {
            bkStoreTime = bkStoreTimes.get(0);
        } else {
            bkStoreTime = new BkStoreTime();
        }
        bkStoreTime.setStoreName(store_name);
        bkStoreTime.setGlobalId(global_id);
        bkStoreTime.setDayOfWeekMon1Sun7(day_of_week_mon1_sun7);
        bkStoreTime.setBeginDate(StringConverters.ToDateOnly(begin_date));
        bkStoreTime.setEndDate(StringConverters.ToDateOnly(end_date));
        bkStoreTime.setBusinessOpenTime(business_open_time);
        bkStoreTime.setBusinessCloseTime(business_close_time);
        bkStoreTime.setOpenTime(StringConverters.ToDateTime(begin_date + " " + business_open_time));
        bkStoreTime.setCloseTime(StringConverters.ToDateTime(end_date + " " + business_close_time));
        this.addOrUpdate(bkStoreTime);
    }

    /**
     * 查询门店这个时间点是否有关闭的
     */
    @Transactional
    public void storeCloseDay() {
        Date today = new Date();
        Date yesterday = DateTimeUtils.addDayOfMonth(today, -1);
        Integer week = StringConverters.getWeekDay(yesterday);
        try {
            List objects = this.getStoreTimeDayJob(week);
            for (Object object : objects) {
                net.sf.json.JSONArray j = net.sf.json.JSONArray.fromObject(object);
                String business_open_time = AliObjectConversion.getJsonString(j, 0);
                String business_close_time = AliObjectConversion.getJsonString(j, 1);
                String inst_ids = AliObjectConversion.getJsonString(j, 2);
                if (StringUtils.isBlank(inst_ids)) {
                    continue;
                }
                JSONArray hostids = new JSONArray();
                hostids.addAll(Arrays.asList(inst_ids.split(",")));
                JSONObject pushJson = new JSONObject();
                pushJson.put("jsonrpc", "2.0");
                pushJson.put("method", "maintenance.create");
                pushJson.put("id", "1");
                JSONObject params = new JSONObject();
                params.put("active_since", StringConverters.dateToStamp(DateTimeUtils.format(yesterday, "yyyy-MM-dd") + " " + business_close_time));
                params.put("active_till", StringConverters.dateToStamp(DateTimeUtils.format(today, "yyyy-MM-dd") + " " + business_open_time));
                params.put("hostids", hostids);
                params.put("name", "星期" + week + "，" + business_close_time + "到" + business_open_time + "维护窗口");
                JSONObject timeperiod = new JSONObject();
                timeperiod.put("timeperiod_type", 3);
                timeperiod.put("every", 1);
                timeperiod.put("dayofweek", 64);
                timeperiod.put("start_time", 64800);
                timeperiod.put("period", 3600);
                JSONArray timeperiods = new JSONArray();
                timeperiods.add(timeperiod);
                params.put("timeperiods", timeperiods);
                pushJson.put("params", params);
                BkResult result = blueKingProcessor.updateZabbixProcessor(pushJson);
                JobStoreTime jobStoreTime = JobStoreTime.builder()
                        .jobTime(new Date())
                        .businessOpenTime(business_open_time)
                        .businessCloseTime(business_close_time)
                        .dayOfWeekMon1Sun7(week)
                        .pushMsg(pushJson.toString())
                        .resultMsg(result.toString())
                        .build();
                jobStoreTimeService.addOrUpdate(jobStoreTime);
            }
        } catch (Exception e) {
            logger.info("解析数据异常");
        }
    }
}
